package ch.zhaw.swp1.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import ch.zhaw.swp1.model.message.Email;
import ch.zhaw.swp1.model.message.MMS;
import ch.zhaw.swp1.model.message.Message;
import ch.zhaw.swp1.model.message.Print;
import ch.zhaw.swp1.model.message.SMS;
import ch.zhaw.swp1.model.message.address.Address;
import ch.zhaw.swp1.model.message.address.EmailAddress;
import ch.zhaw.swp1.model.message.address.MMSAddress;
import ch.zhaw.swp1.model.message.address.PrintAddress;
import ch.zhaw.swp1.model.message.address.SMSAddress;
import ch.zhaw.swp1.model.message.body.EmailBody;
import ch.zhaw.swp1.model.message.body.MMSBody;
import ch.zhaw.swp1.model.message.body.PrintBody;
import ch.zhaw.swp1.model.message.body.SMSBody;
import ch.zhaw.swp1.util.MultiChannelParser;
import ch.zhaw.swp1.view.GUI;

/**
 * Class representing a controller to take action on user commands from GUI 
 * @author Daniel Tiefenauer
 */
public class MultiChannelController {

	private static MultiChannelController controller; // Singleton instance
	private static final String defaultFile = "messages.ser"; // default file path to store messages


	/************************************************************************************/
	/* Constructors ==> SINGLETON
	/*----------------------------------------------------------------------------------*/
	/**
	 * Singleton
	 * @return singleton controller object
	 */
	public static MultiChannelController getInstance(){
		if(controller == null){
			controller = new MultiChannelController();
		}
		return controller;
	}

	/************************************************************************************/
	/* Methods
	/*----------------------------------------------------------------------------------*/
	/**
	 * This method is executed by the GUI when the user clicks on the "Send"-Button
	 * @param gui a reference to the GUI containing the user entered data
	 */
	public void processMessage(GUI gui) {
		Message message = createMessage(gui);
		message.addObserver(gui);
		message.process();
	}
	
	/**
	 * Create a message from user input
	 * @param gui GUI containing user input
	 * @return a message of user defined type
	 */
	private Message createMessage(GUI gui){
		Message message = null;
		
		switch (gui.getMessageType()){
		case SMS:
			message = new SMS();
			break;
		case MMS:
			message = new MMS();
			break;
		case EMAIL:
			message = new Email();
			break;
		case PRINT:
			message = new Print();
			break;
		}
				
		// RECIPIENTS
		List<Address> recipients = MultiChannelParser.parseRecipients(gui.getRecipients(), gui.getMessageType());
		Iterator<Address> it = recipients.iterator();
		while(it.hasNext()){
			message.addRecipient(it.next());
		}
		
		// SEND TIME
		if (gui.getSendDate() != null){
			message.setSendDate(gui.getSendDate());
		}
		
		// TYPE SPECIFIC DATA
		setSpecificData(message, gui);
		
		return message;
		
	}
	
	/**
	 * Set specific data depending on message type
	 * @param message
	 * @param gui
	 */
	private void setSpecificData(Message message, GUI gui){
		
		switch(message.getMessageType()){
		
		case SMS:
			// SENDER
			message.setSender(new SMSAddress(gui.getSender()));
			// BODY
			message.setBody(new SMSBody(gui.getMessageText()));
			break;
			
		case MMS:
			// SENDER
			message.setSender(new MMSAddress(gui.getSender()));
			// BODY
			message.setBody(new MMSBody(gui.getMessageText()));
			((MMS)message).setAttachments(gui.getAttachments());
			break;
			
		case EMAIL:
			// SENDER
			message.setSender(new EmailAddress(gui.getSender()));
			// BODY
			message.setBody(new EmailBody(gui.getMessageText()));
			// Attachments
			((Email)message).setAttachments(gui.getAttachments());
			break;
			
		case PRINT:
			// SENDER
			message.setSender(new PrintAddress(gui.getSender()));
			// BODY
			message.setBody(new PrintBody(gui.getMessageText()));
			break;
		}
	}

	
	/**
	 * This method is executed when the user clicks on the "Load"-Button
	 * @param file A file representing the file on the harddisk to load the messages from
	 * @throws FileNotFoundException
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings("unchecked")
	public void loadMessages(File file) throws FileNotFoundException, IOException, ClassNotFoundException {
		
		file.createNewFile(); // create file if it doesn't exist yet

		FileInputStream fin = new FileInputStream(file);
		ObjectInputStream in = new ObjectInputStream(fin);
		MessageHandler.setMessages((Vector<Message>) in.readObject());
		in.close();
	}

	/**
	 * Save all messages in a file
	 * @param file A file representing the file on the harddisk to save the messages to
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public void saveMessages(File file)	throws FileNotFoundException, IOException {
		
		file.createNewFile(); // create file if it doesn't exist yet

		FileOutputStream fout = new FileOutputStream(file);
		ObjectOutputStream out = new ObjectOutputStream(fout);
		out.writeObject(MessageHandler.getMessages());
		out.close();
	}
	
	/**
	 * Overloaded method to load from default file
	 * @throws FileNotFoundException
	 * @throws ClassNotFoundException
	 * @throws IOException
	 */
	public void loadMessages() throws FileNotFoundException, ClassNotFoundException, IOException {
		loadMessages(new File(defaultFile));
	}
	
	/**
	 * Overloaded method to save to default file
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public void saveMessages() throws FileNotFoundException, IOException{
		saveMessages(new File(defaultFile));
	}

}
